package com.zhuoyue.web.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zhuoyue.biz.core.api.domain.*;
import com.zhuoyue.biz.core.api.dto.rep.SolVoiceSetSceneRepDTO;
import com.zhuoyue.biz.core.api.dto.rep.SolVoiceSetVirtualDeviceRepDTO;
import com.zhuoyue.biz.core.api.dto.req.CommonReq;
import com.zhuoyue.biz.core.api.dto.req.ControlReq;
import com.zhuoyue.biz.core.api.dto.req.SolVoiceSetSceneReqDTO;
import com.zhuoyue.biz.core.api.dto.req.SolVoiceSetVirtualDeviceReqDTO;
import com.zhuoyue.biz.core.api.service.DeviceTaskService;
import com.zhuoyue.biz.core.api.service.GroupService;
import com.zhuoyue.biz.core.api.service.ZigbeeDevicePropertyService;
import com.zhuoyue.biz.core.api.service.impl.DeviceService;
import com.zhuoyue.biz.core.api.service.impl.LocalSceneService;
import com.zhuoyue.biz.core.api.service.impl.SetSolVoiceSceneService;
import com.zhuoyue.biz.core.api.service.impl.SetSolVoiceVirtualDeviceService;
import com.zhuoyue.common.aop.auth.CheckLogin;
import com.zhuoyue.common.constant.ControlType;
import com.zhuoyue.common.dto.ControllerResult;
import com.zhuoyue.common.exception.ErrorType;
import com.zhuoyue.common.exception.ZyServerException;
import com.zhuoyue.common.utils.CmdUtils;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author wjming
 */
@RestController
@Scope("prototype")
@RequestMapping("/api/sol/voice")
@Validated
public class AppSolVoiceController {

    @Autowired
    private SetSolVoiceSceneService setSolVoiceSceneService;

    @Autowired
    private SetSolVoiceVirtualDeviceService setSolVoiceVirtualDeviceService;

    @Autowired
    private LocalSceneService localSceneService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AppCmdController appCmdController;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private GroupService groupService;

    @Autowired
    private DeviceTaskService deviceTaskService;
    @Autowired
    private ZigbeeDevicePropertyService zigbeeDevicePropertyService;

    /**
     * 通过设备ID获取设备场景配置信息
     *
     * @param voiceId
     * @return
     */

    @GetMapping("/scene")
    @CheckLogin
    public ControllerResult getRelationSceneList(@RequestParam @NotBlank(message = "设备ID不能为空！") String voiceId) {
        List<SolVoiceSetSceneRepDTO> solVoiceSetSceneReps = setSolVoiceSceneService.getList(voiceId);
        return ControllerResult.toReturnDataSuccess("查询成功", solVoiceSetSceneReps);
    }

    /**
     * 通过Id获取场虚拟设备列表
     *
     * @param voiceId
     * @return
     */
    @GetMapping("/virtual/device")
    @CheckLogin
    public ControllerResult getRelationDeviceList(@RequestParam @NotBlank(message = "设备ID不能为空！") String voiceId) {
        List<SolVoiceSetVirtualDeviceRepDTO> solVoiceSetVirtualDeviceReps = setSolVoiceVirtualDeviceService.getList(voiceId);
        return ControllerResult.toReturnDataSuccess("查询成功", solVoiceSetVirtualDeviceReps);
    }


    /**
     * 添加场景
     *
     * @return
     */
    @PostMapping("/add/scene")
    @CheckLogin
    public ControllerResult addScene(@RequestBody SolVoiceSetSceneReqDTO solVoiceSetScene) {
        //验证场景是否存在
        LocalSceneDO scene = localSceneService.getById(solVoiceSetScene.getEndSceneId());
        if (scene == null) {
            return ControllerResult.toFail("该场景不存在");
        }
        //验证设备是否存在
        DeviceDO device = deviceService.getById(solVoiceSetScene.getVoiceId());

        if (device == null) {
            return ControllerResult.toParamFail("语音设备不存在");
        }
        //验证关系是否存在
        int count = setSolVoiceSceneService.count(Wrappers.<SetSolVoiceScene>lambdaQuery()
                .eq(SetSolVoiceScene::getVoiceId, solVoiceSetScene.getVoiceId())
                .eq(SetSolVoiceScene::getEndSceneId, solVoiceSetScene.getEndSceneId()));
        if (count > 0) {
            return ControllerResult.toParamFail("关系信息已存在");
        }
        //自动生成code
        Integer odCode = createOdCode(solVoiceSetScene.getVoiceId());

        Integer code = scene.getCode();
        SetSolVoiceScene setSolVoiceScene = new SetSolVoiceScene().dtoToDo(solVoiceSetScene);
        setSolVoiceScene.setSceneChildOd(odCode);

        String sceneCommandCodeEnum = SceneCommandCodeEnum.getSceneCommandCodeEnum(solVoiceSetScene.getVoiceSceneNumber());

        setSolVoiceScene.setVoiceCommandName(sceneCommandCodeEnum);

        String toJsonStr = JSON.toJSONString(setSolVoiceScene);
        redisTemplate.opsForValue().set(device.getZigbeeMac() + "_" + odCode + "_add", toJsonStr, 5, TimeUnit.SECONDS);
        sendSceneCmd(odCode, CmdUtils.intToHexTwo(code), solVoiceSetScene);
        return ControllerResult.toReturnDataSuccess("绑定成功", null);
    }


    /**
     * 添加虚拟设备信息
     *
     * @return
     */
    @PostMapping("/add/virtual")
    @CheckLogin
    public ControllerResult addVirtual(@RequestBody SolVoiceSetVirtualDeviceReqDTO solVoiceSetVirtualDeviceReq) {
        final String group = "group";
        //验证语音设备是否存在
        DeviceDO device = deviceService.getById(solVoiceSetVirtualDeviceReq.getVoiceId());

        if (device == null) {
            return ControllerResult.toParamFail("语音设备不存在");
        }
        solVoiceSetVirtualDeviceReq.setGatewayId(device.getGatewayId());

        String virtualType = solVoiceSetVirtualDeviceReq.getVirtualType();
        DeviceDO endDevice = null;
        Group groupClass = null;
        String mac = "";

        if (StringUtils.containsIgnoreCase(virtualType, group)) {
            groupClass = groupService.getById(solVoiceSetVirtualDeviceReq.getEndDeviceId());
            if (groupClass != null) {
                mac = groupClass.getCode() + "00000000000000";
            }
        } else {
            //验证结束设备是否存在
            endDevice = deviceService.getById(solVoiceSetVirtualDeviceReq.getEndDeviceId());
            mac = endDevice.getZigbeeMac();
        }

        if (endDevice == null && groupClass == null) {
            return ControllerResult.toParamFail("添加的设备不存在");
        }

        String virtualDeviceTypeEnum = VirtualDeviceTypeEnum.getVirtualDeviceTypeEnum(solVoiceSetVirtualDeviceReq.getVirtualType());
        if (StringUtils.isEmpty(virtualDeviceTypeEnum)) {
            return ControllerResult.toParamFail("类型不匹配");
        }

        SetSolVoiceVirtualDevice setSolVoiceVirtualDevice = new SetSolVoiceVirtualDevice().dtoToDo(solVoiceSetVirtualDeviceReq);
        setSolVoiceVirtualDeviceService.verifyThatTheAddedDeviceIs(setSolVoiceVirtualDevice);
        String toJsonStr = JSON.toJSONString(setSolVoiceVirtualDevice);
        redisTemplate.opsForValue().set(device.getZigbeeMac() + "_1B5B" + "_add", toJsonStr, 5, TimeUnit.SECONDS);
        sendVirtualCmd(mac, virtualDeviceTypeEnum, solVoiceSetVirtualDeviceReq, solVoiceSetVirtualDeviceReq.getAddress());
        return ControllerResult.toReturnDataSuccess("绑定成功", null);
    }

    /**
     * 修改配置的场景
     *
     * @return
     */
    @PutMapping("/put/scene")
    @CheckLogin
    public ControllerResult putScene(@RequestBody SolVoiceSetSceneReqDTO solVoiceSetScene) {
        SetSolVoiceScene solVoiceScene = setSolVoiceSceneService.getById(solVoiceSetScene.getId());

        LocalSceneDO scene = localSceneService.getById(solVoiceSetScene.getEndSceneId());
        if (scene == null) {
            return ControllerResult.toFail("该场景不存在");
        }
        DeviceDO device = deviceService.getById(solVoiceSetScene.getVoiceId());
        if (device == null) {
            return ControllerResult.toFail("语音设备不存在");
        }


        //验证关系是否存在
        SetSolVoiceScene one = setSolVoiceSceneService.getOne(Wrappers.<SetSolVoiceScene>lambdaQuery()
                .eq(SetSolVoiceScene::getVoiceId, solVoiceSetScene.getVoiceId())
                .eq(SetSolVoiceScene::getEndSceneId, solVoiceSetScene.getEndSceneId()));
        if (one != null) {
            if (!one.getId().equals(solVoiceSetScene.getId())) {
                return ControllerResult.toParamFail("关系信息已存在,请先解绑");
            }
        }

        Integer code = scene.getCode();

        SetSolVoiceScene setSolVoiceScene = new SetSolVoiceScene().dtoToDo(solVoiceSetScene);
        setSolVoiceScene.setSceneChildOd(solVoiceScene.getSceneChildOd());
        String sceneCommandCodeEnum = SceneCommandCodeEnum.getSceneCommandCodeEnum(solVoiceSetScene.getVoiceSceneNumber());
        setSolVoiceScene.setVoiceCommandName(sceneCommandCodeEnum);
        String toJSONString = JSON.toJSONString(setSolVoiceScene);
        redisTemplate.opsForValue().set(device.getZigbeeMac() + "_" + solVoiceScene.getSceneChildOd() + "_update", toJSONString, 5, TimeUnit.SECONDS);
        sendSceneCmd(solVoiceScene.getSceneChildOd(), CmdUtils.intToHexTwo(code), solVoiceSetScene);
        return ControllerResult.toReturnDataSuccess("更改成功", null);
    }

    /**
     * 修改虚拟设备信息
     *
     * @return
     */
    @PutMapping("/put/virtual")
    @CheckLogin
    public ControllerResult setVirtual(@RequestBody SolVoiceSetVirtualDeviceReqDTO solVoiceSetVirtualDeviceReq) {
        final String group = "group";
        //验证语音设备是否存在
        DeviceDO device = deviceService.getById(solVoiceSetVirtualDeviceReq.getVoiceId());

        if (device == null) {
            return ControllerResult.toParamFail("语音设备不存在");
        }
        solVoiceSetVirtualDeviceReq.setGatewayId(device.getGatewayId());

        String virtualType = solVoiceSetVirtualDeviceReq.getVirtualType();
        DeviceDO endDevice = null;
        Group groupClass = null;
        String mac = "";
        if (StringUtils.containsIgnoreCase(virtualType, group)) {
            groupClass = groupService.getById(solVoiceSetVirtualDeviceReq.getEndDeviceId());
            if (groupClass != null) {
                mac = groupClass.getCode() + "00000000000000";
            }
        } else {
            //验证结束设备是否存在
            endDevice = deviceService.getById(solVoiceSetVirtualDeviceReq.getEndDeviceId());
            if (groupClass != null) {
                mac = endDevice.getZigbeeMac();
            }
        }

        if (endDevice == null && groupClass == null) {
            return ControllerResult.toParamFail("添加的设备不存在");
        }

        String virtualDeviceTypeEnum = VirtualDeviceTypeEnum.getVirtualDeviceTypeEnum(solVoiceSetVirtualDeviceReq.getVirtualType());
        if (StringUtils.isEmpty(virtualDeviceTypeEnum)) {
            return ControllerResult.toParamFail("类型不匹配");
        }

        SetSolVoiceVirtualDevice setSolVoiceVirtualDevice = new SetSolVoiceVirtualDevice().dtoToDo(solVoiceSetVirtualDeviceReq);
        String toJsonStr = JSON.toJSONString(setSolVoiceVirtualDevice);
        redisTemplate.opsForValue().set(device.getZigbeeMac() + "_1B5B" + "_update", toJsonStr, 5, TimeUnit.SECONDS);
        sendVirtualCmd(mac, virtualDeviceTypeEnum, solVoiceSetVirtualDeviceReq, solVoiceSetVirtualDeviceReq.getAddress());
        return ControllerResult.toReturnDataSuccess("更改成功", null);
    }

    /**
     * 删除配置的场景
     *
     * @return
     */
    @DeleteMapping("/del/scene")
    @CheckLogin
    public ControllerResult delScene(String id) {
        SetSolVoiceScene byId = setSolVoiceSceneService.getById(id);
        if (byId == null) {
            return ControllerResult.toParamFail("设备不存在");
        }
        SolVoiceSetSceneReqDTO solVoiceSetSceneReqDTO = new SolVoiceSetSceneReqDTO();
        solVoiceSetSceneReqDTO.setVoiceSceneNumber("FFFF");
        solVoiceSetSceneReqDTO.setVoiceId(byId.getVoiceId());
        sendSceneCmd(byId.getSceneChildOd(), "FF", solVoiceSetSceneReqDTO);

        boolean b = setSolVoiceSceneService.removeById(id);
        if (!b) {
            return ControllerResult.toParamFail("解绑失败");
        }
        return ControllerResult.toReturnDataSuccess("解绑成功", "");
    }

    /**
     * 删除配置的虚拟设备信息
     *
     * @return
     */
    @DeleteMapping("/del/virtual")
    @CheckLogin
    public ControllerResult delVirtual(String id) {
        SetSolVoiceVirtualDevice byId = setSolVoiceVirtualDeviceService.getById(id);
        if (byId == null) {
            return ControllerResult.toParamFail("设备不存在");
        }
        SolVoiceSetVirtualDeviceReqDTO solVoiceSetVirtualDeviceReq = new SolVoiceSetVirtualDeviceReqDTO();
        solVoiceSetVirtualDeviceReq.setVoiceId(byId.getVoiceId());

        String virtualDeviceTypeEnum = VirtualDeviceTypeEnum.getVirtualDeviceTypeEnum(byId.getVirtualType());
        sendVirtualCmd("FFFFFFFFFFFFFFFF", virtualDeviceTypeEnum, solVoiceSetVirtualDeviceReq, "FF");
        boolean b = setSolVoiceVirtualDeviceService.removeById(id);
        if (!b) {
            return ControllerResult.toParamFail("解绑失败");
        }
        return ControllerResult.toReturnDataSuccess("解绑成功", "");
    }

    @DeleteMapping("/del/all")
    @CheckLogin
    public ControllerResult restVoice(String voiceId) {
        DeviceDO byId = deviceService.getById(voiceId);
        if (byId == null) {
            return ControllerResult.toParamFail("设备不存在");
        }
        CommonReq commonReq = CommonReq.controlBaseCmdReq(voiceId, new HashMap<>(0), ControlType.Sol.REST);
        appCmdController.cmdDeviceSend(commonReq);
        setSolVoiceVirtualDeviceService.remove(Wrappers.<SetSolVoiceVirtualDevice>lambdaQuery()
                .eq(SetSolVoiceVirtualDevice::getVoiceId, voiceId));
        setSolVoiceSceneService.remove(Wrappers.<SetSolVoiceScene>lambdaQuery()
                .eq(SetSolVoiceScene::getVoiceId, voiceId));
        deviceTaskService.deleteAll(byId.getZigbeeMac());
        zigbeeDevicePropertyService.removeById(voiceId);
        return ControllerResult.toReturnDataSuccess("重置成功请稍等5秒等待设备重启", "");
    }


    /**
     * 发送场景数据帧
     *
     * @param odCode
     * @param code
     * @param solVoiceSetScene
     */
    private void sendSceneCmd(Integer odCode, String code, SolVoiceSetSceneReqDTO solVoiceSetScene) {
        //生成Action信息
        Map<String, Object> actions = new HashMap<>(2);
        actions.put("eventCode", "0" + odCode);
        actions.put("sceneCode", code);
        actions.put("voiceSceneCode", solVoiceSetScene.getVoiceSceneNumber());

        dealCommonReq(solVoiceSetScene.getVoiceId(), ControlType.SET_SCENE, actions);
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        dealCommonReq(solVoiceSetScene.getVoiceId(), ControlType.VOICE_COMMAND, actions);
    }

    private void sendVirtualCmd(String endZigbeeMac, String virtualDeviceTypeEnum, SolVoiceSetVirtualDeviceReqDTO solVoiceSetVirtualDeviceReq, String address) {
        //生成Action信息
        Map<String, Object> actions = new HashMap<>(2);
        actions.put("endDeviceMac", endZigbeeMac);
        if (StringUtils.isEmpty(address)) {
            actions.put("address", "01");
        } else {
            String[] s = StringUtils.split(address, "_");
            if (s.length > 1) {
                int i = Integer.parseInt(s[1]) + 1;
                String i1 = "";
                if (i < 10) {
                    i1 = "0" + i;
                } else {
                    i1 = i + "";
                }
                actions.put("address", i1);
            } else {
                actions.put("address", s[0]);
            }

        }

        dealCommonReq(solVoiceSetVirtualDeviceReq.getVoiceId(), virtualDeviceTypeEnum, actions);
    }

    private void dealCommonReq(String deviceId, String controlType, Map<String, Object> actions) {
        CommonReq commonReq = new CommonReq();
        commonReq.setDeviceId(deviceId);
        commonReq.setPurpose("CONTROL");
        ControlReq controlReq = new ControlReq();
        controlReq.setActions(actions);
        controlReq.setControlType(controlType);
        commonReq.setControlParam(controlReq);
        appCmdController.cmdDeviceSend(commonReq);
    }

    private synchronized Integer createOdCode(String voiceId) {
        List<Integer> codes = setSolVoiceSceneService.selectCode(voiceId);
        if (codes.size() >= 8) {
            throw new ZyServerException(ErrorType.Service_Fail.getCode(), "联控配置已满");
        }
        if (CollectionUtils.isEmpty(codes)) {
            return 1;
        }

        for (int i = 1; i <= 8; i++) {
            if (codes.size() < i) {
                return i;
            }
            if (i != codes.get(i - 1)) {
                return i;
            }
        }

        return 1;
    }


}


@Getter
enum SceneCommandCodeEnum {

    /**
     * 打开灯
     */
    scene01("0A01", "打开灯", "好的/未配置"),

    /**
     * 打开灯
     */
    scene02("0A02", "关闭灯", "好的/未配置"),

    /**
     * 除湿模式
     */
    scene03("0A03", "我走了", "好的/未配置"),

    /**
     * 送风模式
     */
    scene04("1A01", "明亮场景|明亮模式", "明亮场景已启动/未配置"),

    /**
     * 低风
     */
    scene05("1A02", "温馨场景|温馨模式", "温馨场景已启动/未配置"),

    /**
     * 中风
     */
    scene06("1A03", "柔光场景|柔光模式", "柔光场景已启动/未配置"),

    /**
     * 高风
     */
    scene07("1A04", "全关场景|全关模式", "全关场景已启动/未配置"),

    /**
     * 自动
     */
    scene08("1A05", "用餐场景|用餐模式", "用餐场景已启动/未配置"),
    scene09("1A06", "观影场景|观影模式|我要看电视", "观影场景已启动/未配置"),
    scene10("1A07", "睡眠场景|睡眠模式|我要睡觉了", "用餐场景已启动/未配置"),
    scene11("1A08", "晨起场景|晨起模式|我要起床了", "晨起场景已启动/未配置"),
    scene12("1A09", "阅读场景|阅读模式|我要看书了|我要学习了", "阅读场景已启动/未配置"),
    scene13("1A0A", "起夜场景|起夜模式", "起夜场景已启动/未配置"),
    scene14("1A0B", "会客场景|会客模式", "会客场景已启动/未配置"),
    scene15("1A0C", "卓悦场景|卓悦模式", "卓悦场景已启动/未配置"),
    scene16("1A0D", "演示场景|演示模式", "演示场景已启动/未配置"),
    scene17("1A0E", "会议场景|会议模式", "会议场景已启动/未配置");


    private String key;
    private String value;
    private String reVoice;

    SceneCommandCodeEnum(String key, String value, String reVoice) {
        this.key = key;
        this.value = value;
        this.reVoice = reVoice;
    }

    /**
     * 根据Key得到枚举的Value
     * 普通for循环遍历，比较判断
     * <p>
     * 用于比较传入参数是否正确
     *
     * @param key
     * @return
     */
    public static String getSceneCommandCodeEnum(String key) {
        SceneCommandCodeEnum[] eventCodeEnums = SceneCommandCodeEnum.values();
        for (int i = 0; i < eventCodeEnums.length; i++) {
            if (key.equals(eventCodeEnums[i].getKey())) {
                return eventCodeEnums[i].getValue();
            }
        }
        return "";
    }

}

/**
 * 虚拟设备类型枚举
 */
@Getter
enum VirtualDeviceTypeEnum {
    /**
     * 窗帘
     */
    CURTAIN("curtain", ControlType.Sol.SET_VIRTUAL_CURTAIN),
    /**
     * 调光灯
     */
    DIMMINGLAMP("dimmingLamp", ControlType.Sol.SET_VIRTUAL_DIMMING_LAMP),

    /**
     * 智能灯
     */
    INTELLIGENTLAMP("intelligentLamp", ControlType.Sol.SET_VIRTUAL_INTELLIGENT_LAMP),

    /**
     * 空调面板
     */
    AC_PANEL("acPanel", ControlType.Sol.SET_VIRTUAL_AC_PANEL),

    /**
     * 空调控制盒
     */
    ac_Controller("acController", ControlType.Sol.SET_VIRTUAL_AC_CONTROLLER),

    /**
     * 设置群组
     */
    CURTAIN_GROUP("curtainGroup", ControlType.Sol.SET_VIRTUAL_CURTAIN_GROUP),
    /**
     * 调光灯群组
     */
    DIMMING_LAMP_GROUP("dimmingLampGroup", ControlType.Sol.SET_VIRTUAL_DIMMING_LAMP_GROUP),
    /**
     * 智能灯群组
     */
    INTELLIGENT_LAMP_GROUP("intelligentLampGroup", ControlType.Sol.SET_VIRTUAL_INTELLIGENT_LAMP_GROUP);

    private String key;
    private String value;


    VirtualDeviceTypeEnum(String key, String value) {
        this.key = key;
        this.value = value;
    }

    /**
     * 根据Key得到枚举的Value
     * 普通for循环遍历，比较判断
     * <p>
     * 用于比较传入参数是否正确
     *
     * @param key
     * @return
     */
    public static String getVirtualDeviceTypeEnum(String key) {
        VirtualDeviceTypeEnum[] eventCodeEnums = VirtualDeviceTypeEnum.values();
        for (int i = 0; i < eventCodeEnums.length; i++) {
            if (key.equals(eventCodeEnums[i].getKey())) {
                return eventCodeEnums[i].getValue();
            }
        }
        return "";
    }
}

